#!/usr/bin/env python
# coding=UTF-8
# Chen Wen <chenpc@cs.nctu.edu.tw>
# Web Site http://code.google.com/p/edict/
# Blog : http://chenpc.csie.in
import urllib2
import sys,string
from HTMLParser import HTMLParser
from optparse import OptionParser
import shelve,os
import random
from multiprocessing import Process, Queue, Pool

red="\33[31;1m"
lindigo="\33[36;1m"
indigo="\33[36m"
green="\33[32m"
yellow="\33[33;1m"
blue="\33[34;1m"
org="\33[0m"
light="\33[0;1m"
db = shelve.open(os.getenv("HOME")+"/.edict.db","c")
learn=0
class MyHTMLParser(HTMLParser):
	def __init__(self):
		self.show = 0
		self.result=[]
		self.prefix=""
		self.postfix=""
		self.data=""
	def handle_starttag(self, tag, attrs):
		if tag == "span":
			if  attrs[0][1] == "def":
				self.show = 1
				self.prefix=org+"> "
				self.postfix=org
			if attrs[0][1] == "eg":
				self.show = 1
				self.prefix="    %s" %  indigo
				self.postfix=org
			if attrs[0][1] == "ipa":
				self.show = 1
				self.prefix=blue+"["
				self.postfix="]"+org
			if attrs[0][1] == "hw":
				self.show = 1
				self.prefix=light
				self.postfix=org
			if attrs[0][1] == "pos":
				self.show = 1
				self.prefix=red+"<"
				self.postfix=">"+org
	def handle_data(self,data):
		if self.show == 1:
			self.data = "%s%s" % (self.data ,data)
	def handle_endtag(self, tag):
		if self.show == 1 and tag == "span":
			self.show = 0
			self.postfix+="\n"
			self.result.append("%s%s%s" % (self.prefix, self.data, self.postfix))
			self.prefix=""
			self.postfix=""
			self.data=""

def dict_get_result(word):
	try:
		data = urllib2.urlopen(
		"http://dictionary.cambridge.org/dictionary/learner-english/%s" % word).read()
	except urllib2.HTTPError:
		return ""
	start_line = string.index(data, '<h2 id="definition-title" class="cdo-section-title">')
	end_line = string.index(data, '<ul class="cdo-freetools cdo-section">')
	data1 = data[:end_line]
	data1 = data1.replace('<strong class="cl">', lindigo)
	data1 = data1.replace('</strong>', org+indigo)
	p=MyHTMLParser()
	p.reset()
	p.feed(data1)
	return p.result
	
def seckey(x):
        return x[1]

def get_answer(iq, oq):
	while True:
		key = iq.get()
		(result,k) = dict(key)
		oq.put([result, k])

def gen_word(iq, wordlist):

	while True:
		k=wordlist[int(random.triangular(0, len(wordlist)-1, 0))][0]
		iq.put(k)
	
def learnmode():
	totalcount = 0
	lookup = Queue(maxsize = 5)
	answer = Queue(maxsize = 5)

	wordlist = db.items()
	wordlist.sort(key=seckey)
	size=len(wordlist)
	if size < 2:
		print "Not enough words in database"
		exit()

        wordgen = Process( target=gen_word, args=(lookup,wordlist) )
        lookuper = Process( target=get_answer, args=(lookup, answer) )
        wordgen.daemon = True
        lookuper.daemon = True
        wordgen.start()
        lookuper.start()


	while True:
		if totalcount*3 > size:
			wordlist = db.items()
			wordlist.sort(key=seckey)
			size=len(wordlist)
			if size < 2:
				print "Not enough words in database"
				exit()
		[result, k] = answer.get()
		print result.replace(k, "####").replace(k.upper(), "####").replace(k[0].swapcase()+k[1:].lower(),"####")
		try:
			word = raw_input("Input :")
		except KeyboardInterrupt:
			print ""
			db.sync()
			wordgen.terminate()
			lookuper.terminate()
			exit()
		except EOFError:
			print ""
			db.sync()
			wordgen.terminate()
			lookuper.terminate()
			exit()
		if word == "d":
			del db[k]
			wordlist = db.items()
			wordlist.sort(key=seckey)
			size=len(wordlist)
			if size < 2:
				print "Not enough words in database"
				exit()
			continue
		if word == k:
			print "Bingo!"
			db[k]+=3
		else:
			db[k]-=10
			print "The correct anwser is [%s%s%s]" % (red, word, org)
			raw_input("Press any key...")
	
def dict(word):
	word = word.replace(' ', '-')
	subkeyword=word
	endresult=[]
	tempresult=[]
	text="" 
	for x in range(0,3):
		if x > 0:
			subkeyword = "%s_%d" %(word, x)
		tempresult = dict_get_result(subkeyword)
		if len(tempresult) > 0:
			endresult.append(tempresult)
	if len(endresult) > 0:
		if db.has_key(word):
			db[word]+=1
		else:
			db[word]=1
		for lines in endresult:
			for line in lines:
				text+=line
		return text, word
	return yellow+"Not Found!"+org, word

	
def main():
	
        parser = OptionParser(usage = "Usage: ydict [options] word1 word2 ......")
	parser.add_option("-l", "--learn", dest="learn", help="Learning mode.", default=False, action="store_true")
	(options, args) = parser.parse_args()
	if len(args) > 0:
		for w in args:
			print dict(w)[0]
		db.sync()
		exit()
	if options.learn == True:
		learnmode()
	while(1):
		try:
			word=raw_input("<EDict> ")
		except KeyboardInterrupt:
			print ""
			db.sync()
			exit()
		except EOFError:
			print ""
			db.sync()
			exit()
		print dict(word)[0]

if __name__ == '__main__':
	main()

